package com.puzzud.engine.video;

import com.puzzud.engine.video.VideoObject;
import com.puzzud.engine.video.VideoObject2D;
import com.puzzud.engine.video.VideoDisplay;

import com.puzzud.engine.utility.GameShell;

import java.awt.*;
import javax.swing.ImageIcon;

import java.awt.image.*;
import java.awt.geom.AffineTransform;

// VideoImage
public class VideoImage extends VideoObject2D
{
	private Image image;
	GameShell gameShell;
	
	protected int realWidth;
	protected int realHeight;
	
	public VideoImage( GameShell gs )
	{
		super();
		
		gameShell = gs;
	}

        public VideoImage( int width, int height, GameShell gs )
	{
		super( width, height );

                create( width, height );

		gameShell = gs;
	}

        @Override
	public void draw( VideoObject videoObject )
	{
		//VideoDisplay tempVideoDisplay;
		// If we are drawing a VideoDisplay on to this image.
		if( videoObject instanceof VideoDisplay )
                {
                    drawOnTo( ( VideoDisplay )videoObject );
		}
                else
                if( videoObject instanceof VideoImage )
                {
                    draw( ( VideoImage )videoObject );
                }
	}

        public void draw( VideoImage videoImage )
	{
            BufferedImage tempBufferedImage = new BufferedImage( getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB );
            Graphics graphics = tempBufferedImage.createGraphics();
            
            graphics.drawImage( image, 0, 0, gameShell );
            graphics.drawImage( videoImage.getBuffer(), videoImage.getXPosition(), videoImage.getYPosition(), gameShell );
            
            image = tempBufferedImage;
	}
	
	public void drawOnTo( VideoDisplay videoDisplay )
	{
		Graphics2D g2d = videoDisplay.getBuffer();
		Image tempImage = image;
		BufferedImage sourceImage;
		
		sourceImage = new BufferedImage( getRealWidth(),
						 getRealHeight(),
						 BufferedImage.TYPE_INT_ARGB );
		
		sourceImage.createGraphics().drawImage( tempImage, null, gameShell );
		
		final float[] offset = new float[] { 0.0f, 0.0f, 0.0f, 0.0f};
		//RescaleOp rescaleOp = new RescaleOp( colorWeight, offset, null );
		
		if( isScaled() )
		{
			final AffineTransform identity = new AffineTransform();
			AffineTransform at = new AffineTransform();
			
			//at.setTransform( identity );
                        
			// Determine if the scale should be smoothen or exact.
                        if( getScaleType() == VideoObject2D.SCALE_TYPE_EXACT )
                        {
                            g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION,
                                                 RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR );

                        }
                        else
                        {
                             g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION,
                                                   RenderingHints.VALUE_INTERPOLATION_BILINEAR  );
                        }

			g2d.setTransform( at );
			
			if( ( getXScale() == 0 ) && ( getYScale() == 0 ) )
			{
				g2d.scale( 0, 0 );
				
			}
			else
			{
				g2d.translate( getXPosition(), getYPosition() );
				g2d.scale( getXScale(), getYScale() );
			}
			
			//g2d.drawImage( sourceImage, rescaleOp, 0, 0 );
			g2d.drawImage( sourceImage, 0, 0, null );
			
			g2d.setTransform( identity );
		}
		else
		{
			//g2d.drawImage( sourceImage, rescaleOp,
			//	       getXPosition(), getYPosition() );
			g2d.drawImage( sourceImage, getXPosition(), getYPosition(), null );
		}
	}
	
	protected void setRealDimensions( int width, int height )
	{
		if( image != null )
		{
			image = image.getScaledInstance( width, height, Image.SCALE_DEFAULT );
		}
		
		realWidth = width;
		realHeight = height;
	}
	
        @Override
        public int getWidth()
	{
		return( getRealWidth() );
	}

        @Override
	public int getHeight()
	{
		return( getRealHeight() );
	}
        
	int getRealWidth()
	{
		if( image != null )
		{
			realWidth = image.getWidth( gameShell );
		}
		
		return( realWidth );
	}
	
	int getRealHeight()
	{
		if( image != null )
		{
			realHeight = image.getHeight( gameShell );
		}
		
		return( realHeight );
	}
	
	/*
	public void setDimensions( int width, int height )
	{
		super.setDimensions( width, height );
	}
	*/

        public void create( int width, int height )
        {
            image = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
            Graphics graphics = image.getGraphics();
            graphics.fillRect( 0, 0, width, height );

            setRealDimensions( image.getWidth( gameShell ), image.getHeight( gameShell ) );
            setDimensions( getRealWidth(), getRealHeight() );
        }
	
	public void load( String fileName )
	{
		//image = gameShell.getImage( gameShell.getCodeBase(), fileName );
		
		ImageIcon ii = new ImageIcon( this.getClass().getResource( fileName ) );
		image = ii.getImage();
		
		//image = Toolkit.getDefaultToolkit().getImage( fileName );
		
		/*
		if( image != null )
		{
			image = Toolkit.getDefaultToolkit().getImage( fileName );
			
			width = image.getWidth( gameShell );
			height = image.getHeight( gameShell );
		}
		else
		{
			image = gameShell.getImage( gameShell.getCodeBase(), fileName );
		}
		*/
		
		setRealDimensions( image.getWidth( gameShell ), image.getHeight( gameShell ) );
		setDimensions( getRealWidth(), getRealHeight() );
		
		// NOTE Perhaps if I move this media tracking access outside of this object to a single media
		// tracker (perhaps in VideoSystem), things will load more concurrently.
		MediaTracker media_tracker = new MediaTracker( gameShell );

		// add your image to the tracker with an arbitrary id
		int id = 0;
		media_tracker.addImage( image, id );
		
		try
		{
			media_tracker.waitForID( id );
		}
		catch( InterruptedException e )
		{
			
		}

		media_tracker = null;
	}
	
	public Image getBuffer()
	{
		return( image );
	}
	
	// TODO Fix this!!!
	public void copy( Image image )
	{
		this.image = image;
	}
}
